#include <iostream>
#include <vector>
#include <map>
using namespace std;

namespace usingDemo {

#define DString std::string    //! 不建议使用！
typedef std::string TString;   //! 使用typedef的方式
using Ustring = std::string;   //！使用 using 

    //更直观
    typedef void (*tFunc)(void);
    using uFunc = void(*)(void);

    void glFun() { return; }


    class Base
    {
    public:
        Base()
        {}
        ~Base() {}

        void dis1()
        {
            cout << "dis1" << endl;
        }
        void dis2()
        {
            cout << "dis2" << endl;
        }
    };

    class BaseA :private Base//私有继承
    {
    public:
        using Base::dis1;//需要在BaseA的public下释放才能对外使用，  
        void dis2show()
        {
            this->dis2();
        }
    };
    void demo1()
    {
        string str = "china";
        //！字符数组
        for (auto ch : str)
        {
            cout << ch << endl;
        }

        int arr[] = { 1,2,3,4 };
        //！普通数组
        for (auto i : arr)
        {
            cout << i << endl;
        }
        {
        vector<string> vs = { "abc","xyz","mnq" };
        vector<string>::iterator itr = vs.begin();
        for (; itr != vs.end(); itr++)
        {
            cout << *itr << endl;
        }

        //！vector
        for (auto& s : vs)
        {
            cout << s << endl;
        }
       }
        map<int, string> mis = { {1,"c++"},{2,"java"},{3,"python"} };
        map<int, string>::iterator itr = mis.begin();
        for (; itr!=mis.end(); ++itr)
        {
            cout << (*itr).first << "\t" << itr->second << endl;
        }
        //！map
        for (auto& pair : mis)
        {
            cout << pair.first << "\t" << pair.second << endl;
        }

    }
    template<typename R, typename T, typename U>
    R add(T a, U b)
    {
        return a + b;
    }

    template<typename R, typename T, typename U>
    auto add2(T a, U b)->decltype(a + b)
    {
        return a + b;
    }
    class Add3
    {
    public:
        int operator()(int x, int y) //仿函数
        {
            return x + y;
        }
    };
    void demo2()
    {
        int a = 1;
        float b = 1.1;
        auto ret = add<decltype(a + b), int, float>(a, b);
        cout << ret << endl;
        auto ret2 = add2<decltype(a + b)>(a, b);
        cout << ret2 << endl;

        Add3 add3;
        cout << add3(a, b) << endl;
    }
    

    int fun() { return 1; }
    int main()
    {
        demo1();
        demo2();


        BaseA ba;
        ba.dis1();
      //  ba.dis2();  //未使用using
        ba.dis2show();

        TString ts("String!");
        Ustring us("Ustring!");
        string s("sdfdfsd");
        cout << ts << endl;
        cout << us << endl;
        cout << s << endl;

        tFunc f1 = glFun;
        f1();
        uFunc f2 = glFun;
        f2();

        {
        cout << " \n\n path demo \n\n " ;
        string path = "C:\Program Files (x86)\alipay\aliedit\5.1.0.3754"; //转义了
        string path2 = "C:\\Program Files (x86)\\alipay\\aliedit\\5.1.0.3754";
        //更简洁的表示
        string path3 = R"(C:\Program Files (x86)\alipay\aliedit\5.1.0.3754)";
        string path4 = R"(C:\Program "Files" (x86)\\alipay\aliedit\5.1.0.3754)";

        cout << path << endl;
        cout << path2 << endl;
        cout << path3 << endl;
        cout << path4 << endl;

        string path5 = R"( c++多行字符串，可以这么写： \
                    CString s; 
                    abc
                        )";
        cout << path5 << endl;
        wcout << L"     \
            c++多行字符串，可以这么写： \
            CString s;  \
        abc \
            \n ";
        }
        {
            cout << " \n\n decltype(expr) demo \n\n ";
            //decltype(expr); expr 代表被推导的表达式。由decltype推导所声明难过的变量，可初始化，也可不初始化。
            int a = 10;
            cout << sizeof(a) << endl;
            decltype(a) b = 20; //！decltype(a) == int 
            decltype(a + b) c = 30;
            cout << a << b << c << endl;
            const int& cira = a;
            decltype(cira) cirb = b;
            cout << cira << cirb << endl;
            int* pa = &a;
            decltype(pa) pb = &b;
            cout << &a << "\t" << pa << endl;
            cout << &b << "\t" << pb << endl;
            decltype(fun()) df;
            cout << sizeof(df) << endl;
        }
        {
            vector<int> vi = { 1,2,3,4,5,0 };

            typedef decltype(vi.begin()) Itr;

            for (Itr itr = vi.begin(); itr != vi.end(); ++itr)
            {
                cout << *itr << endl;
            }
            map<int, string> mis;
            mis.insert(map<int, string>::value_type(1, "abc"));
            mis.insert(decltype(mis)::value_type(2, "java"));

            typedef decltype(map<int, string>::value_type()) Int2String;

            mis.insert(Int2String(3, "c++"));
            for (auto& is : mis)
            {
                cout << is.first << is.second << endl;
            }
        }

        {
            auto foo = [] { return 1 + 2; };//[]{}闭包+函数体   Lambda 表达式
            cout << foo();
            cout << [] { return 1 + 2; }() << endl;
        }
        {
            auto foo = [](int x, int y)->int {return x + y; };//[]()->{}闭包+参数+返回值+函数体
            cout << foo(1, 2) << endl;
            cout << [](int x, int y) {return x + y; }(1, 2) << endl;
        }
        /*
        []闭包

 lambda 函数能够捕获 lambda 函数外的具有自动存储时期的变量。函数体与这些变
量的集合合起来叫闭包。闭包的概念在 lambda 中通过[]来体现出来。

    [] 不截取任何变量。[bar] 仅对外部变量 bar 值传递在函数体中使用。

    [&bar] 仅对外部变量 bar 引用传递在函数体中使用。

    [x, &y] 仅 x 按值传递，y 按引用传递在函数体中使用。。

    [&} 截取外部作用域中所有变量，并作为引用传递在函数体中使用。

    [=] 截取外部作用域中所有变量，并按值传递在函数体中使用。

    [=, &foo] 截取外部作用域中所有变量，并值传递在函数体中使用，但是对 foo变量使用引用传递。

    [&, =foo] 截取外部作用域中所有变量，在函数体中作引用传递使用，但是对foo 变量作值传递。 

　　上述，中涉及到值传递要发生拷贝行为，而引用传递则不会发生拷贝行为。
  捕获列表中不允许重复。比如：[=, a] [&,&this]。闭包的本质，初始化 lamda 表达式。 

        */
        {   wcout << "\n\n lambda  mutable  demo \n\n";
            int x = 10; int y = 100;
            cout << "main:" << x << y << endl;
            auto foo = [=]()mutable {   //
                x = 20;
                y = 200;
                cout << "lambda:" << x << y << endl;
            };
            foo();
            cout << "main:" << x << y << endl;
        }
        {
            /*
            lambda表达式中[i]值的捕获是发生在编译期的！执行时此时 i=42 值早已拷贝传入。
            所以 i 之后的改变对于表达式运行并无任何影响。　
            也就是说，当声明时lambda表达式对外部变量（i）以赋值的方式捕获后赋给一个“函数指针”，执行该函数指针时，
     捕获的变量 (i) 不与外部发生任何关系，无论外部变量如何改变。要想重新“刷新”内部变量，需要重新声明该lambda表达式。
            */
            wcout << L"\n\n lambda表达式中[i]值的捕获是发生在编译期的！ \n\n";

            int i = 42;
            auto f1 = [i]() {return i + 5; };  
          //  auto f2 = [i]() {return i += 5; };  //i不允许修改
            auto f3 = [&i]() {return i += 5; };  //传引用，允许修改
            auto f4 = [i]()mutable {return i += 5; }; //mutable改变了{return i+=5;} i 的const属性
            i = 0;
            auto j = f1();
            cout << "i=" << i << endl;
            cout << " l = f1(); j=" << j << endl;

            auto f5 = [&i]() {return i += 5; };
            auto k = f5();
            cout << "k = f5(); k=" << k << endl;
            cout << "i=" << i << endl;
            auto l = f1();
            cout << " l = f1(); l=" << l << endl;
            return 0;
        }
        return 0;
    }
}